package jpa.model;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import org.apache.log4j.Logger;

@Entity
public class Produto {
	private static Logger logger = Logger.getLogger(Produto.class);

	/* Atributos normais */
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id_produto")
	private Long produto_id;

	@Column(name = "nome3")
	private String nome;

	private String descricao;

	private Long quantidaDePorPacote;

	private Double peso;

	private String dimensoes;

	private String cor;

	private String campoOpcional;

	private String valorDoCampoOpcional;

	/* Atributos de relacionamento */
	@ManyToMany
	@JoinTable(name = "PRODUTOCATEGORIA", joinColumns = @JoinColumn(name = "id_produto"), inverseJoinColumns = @JoinColumn(name = "id_categoria"))
	private Collection<Categoria> categorias = new ArrayList<Categoria>();

	@ManyToMany
	@JoinTable(name = "FORNECE", joinColumns = @JoinColumn(name = "id_produto"), inverseJoinColumns = @JoinColumn(name = "id_fornecedor"))
	private Collection<Fornecedor> fornecedores = new ArrayList<Fornecedor>();

	@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy = "produtoPai")
	private Collection<Produto> produtosFilhos = new ArrayList<Produto>();

	@ManyToOne
	@JoinColumn(name = "pro_id_produto")
	private Produto produtoPai;

	/* Construtor sem argumentos para o JPA */
	public Produto() {
		/* Uma gambiarra oficial para descobrir quem chamou o construtor */
		try {
			throw new IllegalStateException();
		} catch (IllegalStateException e) {
			StackTraceElement[] stackTrace = e.getStackTrace();
			StackTraceElement stackTraceElement = stackTrace[1];
			if (stackTraceElement.getClassName().equals(
					"sun.reflect.NativeConstructorAccessorImpl")) {
				Produto.logger.debug("JPA construindo um produto");
			} else {
				Produto.logger.info("Construindo um produto");
			}
		}
	}

	/* RELACIONAMENTO COM CATEGORIA */
	public Collection<Categoria> getCategorias() {
		return categorias;
	}

	public void addCategoria(Categoria categoria) {
		this.categorias.add(categoria);
	}

	/* RELACIONAMENTO COM FORNECEDOR */
	public Collection<Fornecedor> getFornecedores() {
		return fornecedores;
	}

	public void addFornecedor(Fornecedor fornecedor) {
		this.fornecedores.add(fornecedor);
	}

	/* RELACIONAMENTO COM PRODUTO */
	public Collection<Produto> getProdutosFilhos() {
		return produtosFilhos;
	}

	public void addProduto(Produto produto) {
		this.produtosFilhos.add(produto);
	}

	public Produto getProdutoPai() {
		return produtoPai;
	}

	public void setProdutoPai(Produto produtoPai) {
		this.produtoPai = produtoPai;
	}

	/* GETTERS E SETTERS */
	public String getCampoOpcional() {
		return campoOpcional;
	}

	public void setCampoOpcional(String campoopcional) {
		this.campoOpcional = campoopcional;
	}

	public String getCor() {
		return cor;
	}

	public void setCor(String cor) {
		this.cor = cor;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public String getDimensoes() {
		return dimensoes;
	}

	public void setDimensoes(String dimensoes) {
		this.dimensoes = dimensoes;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public Double getPeso() {
		return peso;
	}

	public void setPeso(Double peso) {
		this.peso = peso;
	}

	public Long getProduto_id() {
		return produto_id;
	}

	public void setProduto_id(Long produto_id) {
		this.produto_id = produto_id;
	}

	public Long getQuantidaDePorPacote() {
		return quantidaDePorPacote;
	}

	public void setQuantidaDePorPacote(Long quantidadeporpacote) {
		this.quantidaDePorPacote = quantidadeporpacote;
	}

	public String getValorDoCampoOpcional() {
		return valorDoCampoOpcional;
	}

	public void setValorDoCampoOpcional(String valordocampoopcional) {
		this.valorDoCampoOpcional = valordocampoopcional;
	}

	/* Métodos reescritos */
	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result
				+ ((produto_id == null) ? 0 : produto_id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Produto other = (Produto) obj;
		if (produto_id == null) {
			if (other.produto_id != null)
				return false;
		} else if (!produto_id.equals(other.produto_id))
			return false;
		return true;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("\n--------------------" + this.getClass().getName()
				+ "--------------------\n");
		builder.append("Nome: " + this.nome + "\n");
		builder.append("Descrição: " + this.descricao + "\n");
		builder.append("Peso: " + this.peso + "\n");
		builder.append("Dimensões: " + this.dimensoes + "\n");
		builder.append(this.campoOpcional + ": " + this.valorDoCampoOpcional
				+ "\n");
		builder.append("QuantidadePorPacote: " + this.quantidaDePorPacote);
		builder.append("\n--------------------" + this.getClass().getName()
				+ "--------------------\n");
		return builder.toString();
	}

}
